package models;

import java.io.Serializable;
import javax.persistence.*;

import prefix.util.JPAUtil;
import prefix.util.OverallUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * The persistent class for the pay database table.
 * 
 */
@Entity
@Table(name = "PAY")
public class Pay implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @TableGenerator(
            name = "PAY_SEQ",
            table = "SEQUENCE",
            pkColumnName = "NAME",
            pkColumnValue = "PAY_SEQ",
            valueColumnName = "CNT",
            initialValue = 10000,
            allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "PAY_SEQ")
    @Column(unique = true, nullable = false)
    private Integer id;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATE_D")
    private Date createD;

    @Column(name = "DUE_AMOUNT")
    private double dueAmount;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "DUE_D")
    private Date dueD;

    @Column(name = "INT_ACCR")
    private double intAccr;

    @Column(name = "INT_PAID")
    private double intPaid;

    @Column(name = "LATE_FEE_ACCR")
    private double lateFeeAccr;

    @Column(name = "LATE_FEE_PAID")
    private double lateFeePaid;

    @Column(name = "LENDER_FEE_ACCR")
    private double lenderFeeAccr;

    @Column(name = "LENDER_FEE_PAID")
    private double lenderFeePaid;

    @Column(name = "LOAN_ID")
    private Integer loanId;

    @Column(name = "MANAGEMENT_FEE_ACCR")
    private double managementFeeAccr;

    @Column(name = "MANAGEMENT_FEE_PAID")
    private double managementFeePaid;

    @Column(name = "PRNCP_ACCR")
    private double prncpAccr;

    @Column(name = "PRNCP_OUT")
    private double prncpOut;

    @Column(name = "PRNCP_PAID")
    private double prncpPaid;

    @Column(name = "PULL_AMOUNT")
    private double pullAmount;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "PULL_D")
    private Date pullD;

    @Column(name = "RECEIVED_AMOUNT")
    private double receivedAmount;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "RECEIVED_D")
    private Date receivedD;

    private int status;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "STATUS_D")
    private Date statusD;

    private int type;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "UPDATE_D")
    private Date updateD;

    public Pay() {
    }

    public static Pay createEmptyPay(Date dueDate) {
        Pay pay = new Pay();
        pay.setCreateD(new Date());
        pay.setDueD(dueDate);
        pay.setPullD(dueDate);
        pay.setDueAmount(0);
        pay.setPullAmount(0);
        return pay;
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getCreateD() {
        return this.createD;
    }

    public void setCreateD(Date createD) {
        this.createD = createD;
    }

    public double getDueAmount() {
        return this.dueAmount;
    }

    public void setDueAmount(double dueAmount) {
        this.dueAmount = dueAmount;
    }

    public Date getDueD() {
        return this.dueD;
    }

    public void setDueD(Date dueD) {
        this.dueD = dueD;
    }

    public double getIntAccr() {
        return this.intAccr;
    }

    public void setIntAccr(double intAccr) {
        this.intAccr = intAccr;
    }

    public double getIntPaid() {
        return this.intPaid;
    }

    public void setIntPaid(double intPaid) {
        this.intPaid = intPaid;
    }

    public double getLateFeeAccr() {
        return this.lateFeeAccr;
    }

    public void setLateFeeAccr(double lateFeeAccr) {
        this.lateFeeAccr = lateFeeAccr;
    }

    public double getLateFeePaid() {
        return this.lateFeePaid;
    }

    public void setLateFeePaid(double lateFeePaid) {
        this.lateFeePaid = lateFeePaid;
    }

    public double getLenderFeeAccr() {
        return this.lenderFeeAccr;
    }

    public void setLenderFeeAccr(double lenderFeeAccr) {
        this.lenderFeeAccr = lenderFeeAccr;
    }

    public double getLenderFeePaid() {
        return this.lenderFeePaid;
    }

    public void setLenderFeePaid(double lenderFeePaid) {
        this.lenderFeePaid = lenderFeePaid;
    }

    public Integer getLoanId() {
        return this.loanId;
    }

    public void setLoanId(Integer loanId) {
        this.loanId = loanId;
    }

    public double getManagementFeeAccr() {
        return this.managementFeeAccr;
    }

    public void setManagementFeeAccr(double managementFeeAccr) {
        this.managementFeeAccr = managementFeeAccr;
    }

    public double getManagementFeePaid() {
        return this.managementFeePaid;
    }

    public void setManagementFeePaid(double managementFeePaid) {
        this.managementFeePaid = managementFeePaid;
    }

    public double getPrncpAccr() {
        return this.prncpAccr;
    }

    public void setPrncpAccr(double prncpAccr) {
        this.prncpAccr = prncpAccr;
    }

    public double getPrncpOut() {
        return this.prncpOut;
    }

    public void setPrncpOut(double prncpOut) {
        this.prncpOut = prncpOut;
    }

    public double getPrncpPaid() {
        return this.prncpPaid;
    }

    public void setPrncpPaid(double prncpPaid) {
        this.prncpPaid = prncpPaid;
    }

    public double getPullAmount() {
        return this.pullAmount;
    }

    public void setPullAmount(double pullAmount) {
        this.pullAmount = pullAmount;
    }

    public Date getPullD() {
        return this.pullD;
    }

    public void setPullD(Date pullD) {
        this.pullD = pullD;
    }

    public double getReceivedAmount() {
        return this.receivedAmount;
    }

    public void setReceivedAmount(double receivedAmount) {
        this.receivedAmount = receivedAmount;
    }

    public Date getReceivedD() {
        return this.receivedD;
    }

    public void setReceivedD(Date receivedD) {
        this.receivedD = receivedD;
    }

    public Status getStatus() {
        return Status.values()[this.status];
    }

    public void setStatus(Status status) {
        this.status = status.ordinal();
    }

    public Date getStatusD() {
        return this.statusD;
    }

    public void setStatusD(Date statusD) {
        this.statusD = statusD;
    }

    public int getType() {
        return this.type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public Date getUpdateD() {
        return this.updateD;
    }

    public void setUpdateD(Date updateD) {
        this.updateD = updateD;
    }

    public Loan getLoan() {
        return JPAUtil.em().find(Loan.class, this.getLoanId());
    }

    public enum Status {
        FUTURE("FUTURE"),//0
        CURRENT("CURRENT"),//1
        GRACE_PERIOD("GRACE PERIOD"),//2
        LATE_7_30("LATE FOR 7-30 DYAS"),//3
        LATE_30_90("Late more than 30 days"),//4
        LATE_90("Late more than 90 days"),//5
        CLOSE_PAID("Paid"),//6
        CLOSE_PAID_OFF("Paid off"),//7
        CLOSE_UN_PAID("Unpaid"),//8
        NOTIFIED("Notified"),//9
        CHARGE_OFF("Charge off");//10

        private String m_desc;

        private Status(String desc) {
            this.m_desc = desc;
        }

        public String getM_desc() {
            return m_desc;
        }

        public void setM_desc(String m_desc) {
            this.m_desc = m_desc;
        }

    }

    private static Status[] s_closeStatusList = { Status.CLOSE_PAID, Status.CLOSE_PAID_OFF, Status.CLOSE_UN_PAID };

    public static Status[] getCloseStatusList() {
        return s_closeStatusList;
    }

    //========================================================================
    private static Status[] s_openStatusList = { Status.CURRENT, Status.GRACE_PERIOD, Status.LATE_30_90,
            Status.LATE_7_30 };

    public static Status[] getOpenStatusList() {
        return s_openStatusList;
    }

    public static List<Pay> filterLpays(List<Pay> lpayTable, Status... statuses) {

        ArrayList<Pay> retList = new ArrayList<Pay>();

        for (Pay lpay : lpayTable) {
            if (OverallUtil.isIn(lpay.getStatus(), statuses))
                retList.add(lpay);
        }
        return retList;
    }

    public static enum Distribution {
        brMgmtPaid,
        brMgmtBalance,
        LateFeesPaid,
        LateFeesUnpaidBalance,
        InterestPaid,
        InterestUnpaidBalance,
        PrincipalPaid,
        PrincipalUnpaidBalance,
        PrincipalNewOutstanding,
        AmountToDistribute,
    }

}